### This script produces the illustrative plots in the paper. Not dependent on any data source, but does draw on some of the same code. 

### colne and oxford side-by-side

path_to_output = paste0("output/") # to allow output to be put somewhere else   
if(! dir.exists(path_to_output)){
  stop("Destination for output not found. Update 'path_to_output' variable in line 5.\n")
}

options(scipen = 999)

source("utils_pivotality_functions.R")


oxford.vote.shares.2010 = c(.423, .42, .106, .027, .021)
oxford.vote.shares.2015 = c(.457, .289, .127, .069, .044)
colne.valley.vote.shares.2005 = c(.328, .242, .358, .005, .026)
colne.valley.vote.shares.2010 = c(.370, .282, .264, .021, .016)
names(oxford.vote.shares.2010) = names(oxford.vote.shares.2015) = names(colne.valley.vote.shares.2005) = names(colne.valley.vote.shares.2010) = c("con", "ld", "lab", "ukip", "grn")


labels = c("Oxford West, 2010", "Oxford West, 2015", "Colne Valley, 2005", "Colne Valley, 2010")
fns = c("ow10", "ow15", "cv05", "cv10")
vote.share.names = c("oxford.vote.shares.2010", "oxford.vote.shares.2015", "colne.valley.vote.shares.2005", "colne.valley.vote.shares.2010")

the.space = .5
the.names = c("Con", "Lib\nDem", "Lab", "UKIP", "Grn")
the.ylim = c(0,.5)
the.cols = c("blue", "orange", "red", "purple", "green")
the.cex.names = .8

# left side of the figure
pdf(paste0(path_to_output, "oxford_and_cv_2010.pdf"), width = 2, height = 3.55)
par(mfrow = c(2,1), mar = c(3, 4, 2, 1), cex = .64)
for(j in c(1,4)){ 
  barplot(get(vote.share.names[j]), space = the.space, ylim = the.ylim, main = labels[j], ylab = "Vote share", names.arg = the.names, col = the.cols, cex.names = the.cex.names)	
}
dev.off()

# right side of the figure 

piv.vec.ox2010 = pivotal.probabilities.analytical(alpha.vec = oxford.vote.shares.2010*85, increments = 50, as.matrix = F)
piv.vec.cv2010 = pivotal.probabilities.analytical(alpha.vec = colne.valley.vote.shares.2010*85, increments = 50, as.matrix = F)
the.order = order(piv.vec.cv2010)

s = 85
pdf(paste0(path_to_output, "piv_probs_oxford_cv_s_", s, "_comparison_levels.pdf"), width = 4, height = 3.8)
par(mar = c(2,0,0,1), mfrow = c(1,1))
y.offset = .1
x.offset = -.00004
plot(piv.vec.ox2010[the.order], 1:length(piv.vec.ox2010) + y.offset, pch = 19, axes = F, xlab = "", ylab = "", xlim = c(x.offset, 1.1*max(piv.vec.ox2010)), main = "")
points(piv.vec.cv2010[the.order], 1:length(piv.vec.cv2010) - y.offset, pch = 21)

axis(1, at = c(0, .00002, .00004, .00006, .00008)) 
abline(v = 0, lty = 2)

label.vec = names(piv.vec.ox2010)
label.vec = gsub("^p\\.ld", "Lib Dem and", label.vec)
label.vec = gsub("^p\\.lab", "Labour and", label.vec)
label.vec = gsub("^p\\.ukip", "UKIP and", label.vec)
label.vec = gsub("^p\\.grn", "Green and", label.vec)
label.vec = gsub("\\.con", " Con", label.vec)
label.vec = gsub("\\.ld", " Lib Dem", label.vec)
label.vec = gsub("\\.lab", " Labour", label.vec)
label.vec = gsub("\\.ukip", " UKIP", label.vec)
text(x = x.offset, y = max(the.order) + 1 - the.order, label.vec[the.order], cex = .7, adj = 0)
legend("bottomright", pch = c(19, 21), legend = c("Oxford West", "Colne Valley"), bg = "white")

dev.off()



### grid of figs 

## row of barplots for the column labels 

the.space = .5
the.names = c("Con", "Lib\nDem", "Lab", "UKIP", "Grn")
the.ylim = c(0,.5)
the.cols = c("blue", "orange", "red", "purple", "green")
the.cex.names = .8

pdf(paste0(path_to_output, "election_results_oxford_colne_valley.pdf"), width = 8, height = 2.3)
par(mfrow = c(1,4), mar = c(3, 4, 2, 1))
barplot(oxford.vote.shares.2010, space = the.space, ylim = the.ylim, main = "Oxford West, 2010", ylab = "Vote share", names.arg = the.names, col = the.cols, cex.names = the.cex.names)
barplot(oxford.vote.shares.2015, space = the.space, ylim = the.ylim, main = "Oxford West, 2015", names.arg = the.names, col = the.cols, cex.names = the.cex.names)
barplot(colne.valley.vote.shares.2005, space = the.space, ylim = the.ylim, main = "Colne Valley, 2005", names.arg = the.names, col = the.cols, cex.names = the.cex.names)
barplot(colne.valley.vote.shares.2010, space = the.space, ylim = the.ylim, main = "Colne Valley, 2010", names.arg = the.names, col = the.cols, cex.names = the.cex.names)
dev.off()


# column of pref plots 
lab.strong.ld.pref =  c(2, 8, 9, 0, 3)
lab.weak.ld.pref =  c(2, 3, 9, 0, 3)
con.strong.pref = c(8, 5, 1, 4, 0)
con.weak.pref = c(5, 4, 2, 3, 1)
con.strange.pref = c(8, 0, 7, 2, 1)
ld.strange.pref = c(8, 9, 0, 1, 1)
green.strong.pref = c(1, 6, 3, 0, 9)
green.weak.pref = c(1, 4, 2, 0, 5)
ld.strong.pref = c(2, 9, 3, 0, 5)
ld.strong.pref.2 = c(2, 9, 7, 0, 5)
pref.names = c("lab.strong.ld.pref", "lab.weak.ld.pref", "ld.strong.pref.2", "ld.strong.pref", "ld.strange.pref", "con.strong.pref", "con.weak.pref", "green.strong.pref") #  "green.weak.pref")
fns = c("lab1", "lab2", "ld1", "ld2", "con1", "con2", "grn1", "grn2")
labels = c("a", "b", "c", "d", "e", "f", "g", "h", "i")

pdf(paste0(path_to_output, "all_prefs.pdf"), width = 1.9, height = 6.25)
par(mfrow = c(length(pref.names),1), mar = c(2, 3.5, 0.5, 1), cex = .6)
for(j in 1:length(pref.names)){
  plot(c(.75, 5.25), c(0, 10), type = "n", xlab = "", ylab = "", axes = F, main = "")
  axis(1, at = 1:5, labels = c("Con", "LD", "Lab", "UKIP", "Grn"), tcl = 0); axis(2, at = c(0, 5, 10))
  mtext(text = paste0("(", labels[j], ")"), side = 2, las = 1, line = 2, cex = .75)
  the.prefs = get(pref.names[j])
  points(1:5, the.prefs, col = the.cols, pch = 19)
  for(j in 1:5){lines(x = rep(j, 2), y = c(0, the.prefs[j]), col = the.cols[j])}
}
dev.off()	


### now the grid 

### a function that yields tau given ratings, vote share, and s

tau = function(ratings, vote.shares, fave.candidate = NULL, s, increments = 50){
  # adapted from version in strategic_heterogeneity_v8.R
  # ratings and vote shares are vectors, one entry for each candidate. they must have the same length and the same names.
  stopifnot(!is.null(names(ratings)) & !is.null(names(vote.shares)) & names(ratings) == names(vote.shares))
  stopifnot(all.equal(vote.shares >= 0, rep(T, length(vote.shares)), check.attributes = F))
  # fave.candidate identifies the index of the candidate the voter sincerely prefers. ordinarily this would be the one with the highest rating. 
  if(is.null(fave.candidate)){
    fave.candidate = which(ratings == max(ratings))
  }
  stopifnot(length(fave.candidate) == 1) # if not provided, must be unique
  stopifnot(fave.candidate > 0 & fave.candidate <= length(ratings))
  sincere.vec = rep(0, length(ratings)); sincere.vec[fave.candidate] = 1
  # s is the precision in the model of counterfactual elections. 
  stopifnot(s > 0)
  ## okay, on with it. 
  vote.shares[is.na(vote.shares)] = 0
  this.alpha.vec = s*(vote.shares/sum(vote.shares))
  names(this.alpha.vec) = names(vote.shares)
  P.mat = plurality.P.matrix.analytical(alpha.vec = this.alpha.vec, increments = increments, n = 50000)
  u = matrix(ratings, nrow = 1)
  values = u%*%P.mat
  names(values) = names(ratings)
  list(tau = max(values[-fave.candidate]) - values[fave.candidate],
       values = values, P.mat = P.mat)
}


elections = c("oxford.vote.shares.2010", "oxford.vote.shares.2015", "colne.valley.vote.shares.2005", "colne.valley.vote.shares.2010") 

mat = matrix(NA, nrow = length(pref.names), ncol = length(elections))

for(i in 1:length(pref.names)){
  for(j in 1:length(elections)){
    the.ratings = get(pref.names[i])
    the.vote.shares = get(elections[j])
    names(the.ratings) = names(the.vote.shares) = c("Con", "LD", "Lab", "UKIP", "Grn")
    this.tau.out = tau(ratings = the.ratings, vote.shares = the.vote.shares, s = 85)
    mat[i,j] = this.tau.out$tau
  }
}

pdf(paste0(path_to_output, "all_the_taus.pdf"), width = 7, height = 7)
par(mfrow = c(1, ncol(mat)), mar = c(2,1,0,2))
the.max = max(abs(mat))
xlims = c(-the.max, the.max)
for(j in 1:ncol(mat)){
  plot(xlims, c(1,(nrow(mat) + .5)) - .25, type = "n", axes = F, xlab = "", ylab = "")
  abline(v = 0, col = "gray", lty = 2)
  axis(1)
  points(mat[,j], nrow(mat):1, pch = 19)
  for(i in 1:nrow(mat)){
    lines(x = c(0, mat[i,j]), y = rep(nrow(mat) - i + 1, 2))
  }
}
dev.off()


